//
//  GIFTools.swift
//  GifUsage
//
//  Created by han on 2020/12/21.
//  Copyright © 2020 Ting Han. All rights reserved.
//

import UIKit
import Photos
import ImageIO
import MobileCoreServices

class GIFTools {
    static func gifImages(withGIFData data: Data) -> [UIImage] {
        var images = [UIImage]()
        let option = [String(kCGImageSourceShouldCache) : kCFBooleanFalse] as CFDictionary
        // 设置不对解码后的位图缓存
        let imageSource = CGImageSourceCreateWithData(data as CFData, option) ?? CGImageSourceCreateIncremental(option)
        let frameCount = CGImageSourceGetCount(imageSource)
        for index in 0 ..< frameCount {
            guard let imageRef = CGImageSourceCreateImageAtIndex(imageSource, index, nil) else { return  images }
            
            let image = UIImage(cgImage: imageRef)
            let newImage = UIImage(data: image.pngData()!)
            images.append(newImage!)
        }
        return images
    }
    static func gifImages(withGIFNamed imageName: String, bundle: Bundle = .main) -> [UIImage] {
        guard let extensionRemoved = imageName.components(separatedBy: ".")[safe: 0],
              let imagePath = bundle.url(forResource: extensionRemoved, withExtension: "gif"),
              let data = try? Data(contentsOf: imagePath) else { return [UIImage]() }
        return gifImages(withGIFData: data)
    }
    
    static func gifImages(withGIFPath path: String) -> [UIImage] {
        guard  let data = try?  Data(contentsOf: URL(fileURLWithPath: path)) else { return [UIImage]() }
        return gifImages(withGIFData: data)
    }
    
    static func generateGIF(images: [UIImage], delayTime: TimeInterval = 0.125) -> String? {
        let temp = NSTemporaryDirectory() as NSString
        let timeFormat = DateFormatter()
        timeFormat.dateFormat = "yyyyMMddHHmmss"
        let time = timeFormat.string(from: Date(timeIntervalSinceNow: 0))
        let filePath = temp.appendingPathComponent(time).appending("generate.gif")
        
        let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
        let gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: delayTime]]
        let cfURL = URL(fileURLWithPath: filePath) as CFURL
        if let destination = CGImageDestinationCreateWithURL(cfURL, kUTTypeGIF, images.count, nil) {
            CGImageDestinationSetProperties(destination, fileProperties as CFDictionary?)
            for image in images {
                CGImageDestinationAddImage(destination, image.cgImage!, gifProperties as CFDictionary?)
            }
            CGImageDestinationFinalize(destination)
            return filePath
        }
        return nil
    }
    
    static func saveGIF(_ path: String) {
        // 保存GIF需要通过URL来保存
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: URL(fileURLWithPath: path))
        }, completionHandler: {success, error in
            if !success { print("error creating asset: \(String(describing: error))") }
        })
    }
    
    static func saveImage(_ image: UIImage) {
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAsset(from: image)
        }, completionHandler: {success, error in
            if !success { print("error creating asset: \(String(describing: error))") }
        })
    }
}

func showTips(_ viewController: UIViewController, _ title: String, _ message: String?) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "确定", style: .cancel, handler: nil))
    viewController.present(alert, animated: true, completion: nil)
}


class GIFGenerator {
    
    typealias ProgressHandler = (Double) -> Void
    
    let loopCount: Int
    let frameCount: Int
    let frameDuration: TimeInterval
    
    var duration: TimeInterval?
    
    // 多图片
    var imageAssets = [PHAsset]()
    
    // video
    var asset: PHAsset?
    
    var targetSize: CGSize?
    
    init(asset: PHAsset, frameCount: Int, frameDuration: TimeInterval, loopCount: Int) {
        self.asset = asset
        self.frameCount = frameCount
        self.frameDuration = frameDuration
        self.loopCount = loopCount
    }
    
}


struct VideoTools {
    
    /// 提取帧
    static func fetchFrame(urlAsset: AVURLAsset?, timeScale: CMTimeScale = 10, timeInterval: TimeInterval) -> UIImage? {
        guard let urlAsset = urlAsset else { return nil }
        
        let generator = AVAssetImageGenerator(asset: urlAsset)
        generator.appliesPreferredTrackTransform = true
        generator.apertureMode = AVAssetImageGenerator.ApertureMode.encodedPixels
        // tolerance，高精度时需要，会花费时间
        generator.requestedTimeToleranceAfter = CMTime.zero;
        generator.requestedTimeToleranceBefore = CMTime.zero;
        let time = CMTime(seconds: timeInterval, preferredTimescale: timeScale)
        // 当前时间seconds, scale: 每秒钟多少帧
        var actualTime : CMTime = CMTimeMake(value: 0,timescale: 0)
        guard let cgimage = try? generator.copyCGImage(at: time, actualTime: &actualTime) else { return nil }
        let image = UIImage(cgImage: cgimage)
        print("actualTime" , actualTime)
        return image
    }
    
    static func fetchFrames(movieURL: URL, timeScale: CMTimeScale = 15, completion: ((UIImage?, Bool) -> Void)?) {
        let movieAsset = AVURLAsset(url: movieURL)
        fetchFrames(urlAsset: movieAsset, timeScale: timeScale, completion: completion)
    }
    
    /// 提取所有帧
    static  func fetchFrames(urlAsset: AVURLAsset, timeScale: CMTimeScale = 15, completion: ((UIImage?, Bool) -> Void)?) {
        
        let duration = CMTimeGetSeconds(urlAsset.duration)
        guard duration < 100 else {
            print("视频时间太长了")
            return
        }
        
        let totalFrames = Int64(duration * Double(timeScale)) //获得视频总帧数
        var times = [NSValue]()
        for i in 1 ... totalFrames {
            let time = CMTimeMake(value: i, timescale: timeScale)
            // CMTimeMake(a,b): a当前第几帧，b每秒钟多少帧。当前播放时间a/b
            // CMTimeMakeWithSeconds(a,b): a当前时间，b每秒钟多少帧。
            times.append(NSValue(time:time))
        }
        
        let generator = AVAssetImageGenerator(asset: urlAsset)
        generator.appliesPreferredTrackTransform = true
        // 防止出现偏差
        generator.requestedTimeToleranceBefore = CMTime.zero;
        generator.requestedTimeToleranceAfter = CMTime.zero;
        var currentIndex = 0
        //        var images = [UIImage]()
        generator.generateCGImagesAsynchronously(forTimes: times) { (cmTime, cgImage, nil, result, error) in
            currentIndex += 1
            if result == .succeeded, let cgImage = cgImage {
                let image = UIImage(cgImage: cgImage)
                //                images.append(image)
                completion?(image, currentIndex >= totalFrames)
            } else {
                completion?(nil, currentIndex >= totalFrames)
            }
            
        }
    }
}

